package keer.httpinterface.proxy;

import keer.httpinterface.HttpInterfaceException;
import keer.httpinterface.http.HttpResponse;
import keer.httpinterface.utils.ClassUtils;
import keer.httpinterface.utils.StringUtils;

import java.util.List;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 抽象的响应转换器类，用于将HTTP响应转换为指定的类型
 * @see HttpResponse
 *
 * @author Keer
 * @since 1.0.0
 */
public abstract class ResponseConverter {
    // 存储响应转换器的映射，键为内容类型，值为对应的转换器实例
    private static final Map<String, ResponseConverter> CONVERTERS_CACHE;

    // 静态代码块，用于初始化转换器缓存
    static {
        CONVERTERS_CACHE = new ConcurrentHashMap<>();
        try {
            // 获取当前包下所有ResponseConverter的子类
            List<Class<ResponseConverter>> classes = ClassUtils.getSubClassesByPackage(ResponseConverter.class.getPackage().getName(),
                    ResponseConverter.class);
            for (Class<ResponseConverter> clz : classes) {
                // 实例化每个子类，并将其内容类型作为键，实例作为值存入缓存
                ResponseConverter converter = clz.newInstance();
                CONVERTERS_CACHE.put(converter.contentType(), converter);
            }
        } catch (Exception e) {
            // 如果在初始化转换器缓存时发生异常，则抛出运行时异常
            throw new RuntimeException(e);
        }
    }

    /**
     * 实际的转换逻辑实现，由子类具体实现
     *
     * @param response HTTP响应对象
     * @param resultType 需要转换成的结果类型
     * @return 转换后的对象
     * @throws Exception 转换过程中可能抛出的异常
     */
    protected abstract Object convert0(HttpResponse response, Class<?> resultType) throws Exception;

    /**
     * 获取转换器支持的内容类型，由子类具体实现
     *
     * @return 转换器支持的内容类型
     */
    protected abstract String contentType();

    /**
     * 根据HTTP响应的内容类型，选择合适的转换器进行转换
     *
     * @param response HTTP响应对象
     * @param resultType 需要转换成的结果类型
     * @return 转换后的对象
     * @throws HttpInterfaceException 如果响应状态码不是200，或者没有找到对应的转换器时抛出
     */
    public static Object convert(HttpResponse response, Class<?> resultType) throws HttpInterfaceException  {
        // 检查响应状态码是否为200
        if (response.getStatusCode() == 200) {
            // 根据响应的内容类型获取对应的转换器
            ResponseConverter converter = CONVERTERS_CACHE.get(response.getContentType());
            // 如果没有找到对应的转换器，则抛出异常
            if (converter == null) {
                throw new HttpInterfaceException("No response converter found for:" + response.getContentType());
            }
            try {
                // 使用找到的转换器进行转换
                return converter.convert0(response, resultType);
            } catch (Exception e) {
                // 如果转换过程中发生异常，则抛出运行时异常
                throw new RuntimeException(e);
            }
        } else {
            // 如果响应状态码不是200，则抛出异常，包含状态码和错误信息
            throw new HttpInterfaceException("Http request failed with status code " + response.getStatusCode() +
                    (StringUtils.isBlank(response.getMessage()) ? "" : ":" + response.getMessage()), response.getError());
        }
    }

}
